let myTools = require('./libs/mytools');
let MyBezier = require('./myBezier');

function DetailItem(x, y, degress) {
    this.pos = cc.v2(x, y);
    this.degress = degress;
}

cc.Class({
    extends: cc.Component,

    properties: {
        nd_head: cc.Node,
    },

    ctor() {
        this.lstDetailItem = [];
        this.lstSel = [];
        this._lstBkp = [];
    },

    onLoad() {
        this.graphics = this.node.getComponent(cc.Graphics);
        this.nd_head.zIndex = 1;
    },

    getBkpList() {
        return this._lstBkp;
    },

    addSel(localPos) {
        let gameMap = G.gameMap;
        let nd = cc.instantiate(gameMap.pf_selnode);
        nd.setParent(this.node);
        nd.setPosition(localPos);
        let sel = nd.getComponent('selnode');
        sel.setChain(this);
        this.lstSel.push(sel);
        this._updateGraphics();
        gameMap.setCurSel(sel);
        return sel;
    },

    resetLastSelIdx(idx){
        let sel = this.lstSel.pop();
        this.lstSel.splice(idx,0,sel);
        this._updateGraphics();
    },

    // getSelByIdx(idx){
    //     if(idx < 0 || idx >= this.lstSel.length){
    //         throw new Error(`getSelByIdx idx:${idx} error!`);
    //     }
    //     return this.lstSel[idx];
    // },

    addLstSel(lst) {
        let gameMap = G.gameMap;
        lst.forEach(item => {
            let nd = cc.instantiate(gameMap.pf_selnode);
            nd.setParent(this.node);
            nd.setPosition(item.x, item.y);
            let sel = nd.getComponent('selnode');
            sel.setChain(this);
            this.lstSel.push(sel);
            gameMap.setCurSel(sel);
        });
        this._updateGraphics();
    },

    /**
     * 删除 sel,并且返回 sel 原来在 lstSel 中的索引
     * @param sel
     * @return {number}
     */
    removeSel(sel) {
        let gameApp = G.gameMap;
        let idx = this.lstSel.indexOf(sel);
        myTools.asset(idx >= 0, 'idx should >= 0');
        this.lstSel.splice(idx, 1);
        sel.node.destroy();
        this._updateGraphics();
        gameApp.setCurSel(null);
        return idx;
    },

    moveSel(sel, pos) {
        sel.node.setPosition(pos);
        this._updateGraphics();
    },

    selectSel(localPos) {
        for (let i = 0, len = this.lstSel.length; i < len; ++i) {
            let sel = this.lstSel[i];
            let selnode = sel.node;
            if (window.eui.containPos(selnode, localPos)) {
                return sel;
            }
        }
        return null;
    },

    highlightSel(targetSel) {
        this.lstSel.forEach(sel => {
            if (sel === targetSel) {
                sel.highlight();
            } else {
                sel.unhighlight();
            }
        })
    },

    updateDrawMode(value) {
        this.graphics.lineWidth = value;
        this._updateGraphics();
    },

    _updateGraphics() {

        // 判断是不是当前的chain
        if (G.gameMap.curChain === this) {
            if (window.editor && editor.isInited()) {
                editor.getBkpView().updateChainLen(this.getTotalLen());
            }
        }
        this._updateHead();
        let graphics = this.graphics;
        graphics.clear();
        if (this.lstSel.length < 3) {
            // bkp也要改变,直接清除数据
            this._lstBkp.forEach(bkp=>{
                bkp.clean();
            });
            return;
        }

        let tmpP0 = cc.v2();
        let tmpP1 = cc.v2();
        let tmpP2 = cc.v2();

        this.lstDetailItem.length = 0;
        for (let i = 0, len = this.lstSel.length; i < len - 2; ++i) {
            let cur = this.lstSel[i].node.getPosition();
            let next = this.lstSel[i + 1].node.getPosition();
            let nextnext = this.lstSel[i + 2].node.getPosition();
            if (i === 0) {
                tmpP0.x = cur.x;
                tmpP0.y = cur.y;
            } else {
                tmpP0.x = (cur.x + next.x) / 2;
                tmpP0.y = (cur.y + next.y) / 2;
            }
            tmpP1.x = next.x;
            tmpP1.y = next.y;

            if (i === len - 3) {
                tmpP2.x = nextnext.x;
                tmpP2.y = nextnext.y;
            } else {
                tmpP2.x = (next.x + nextnext.x) / 2;
                tmpP2.y = (next.y + nextnext.y) / 2;
            }

            let myBezier = new MyBezier(tmpP0, tmpP1, tmpP2);
            let lstItems = myBezier.split();
            lstItems.forEach(item => {
                this.lstDetailItem.push(new DetailItem(item[0], item[1], item[2]));
            });
        }
        let startItem = this.lstDetailItem[0];
        graphics.moveTo(startItem.pos.x, startItem.pos.y);
        for (let i = 1, len = this.lstDetailItem.length; i < len; ++i) {
            let item = this.lstDetailItem[i];
            graphics.lineTo(item.pos.x, item.pos.y);
        }
        graphics.stroke();

        this._updateBkps();
    },

    _updateBkps(){
        // bkp也要改变
        this._lstBkp.forEach(bkp=>{
            let itemModel = bkp.getItemModel();
            this.onUpdateBkp(itemModel);
        });
    },

    update() {
        let selectedChain = G.gameMap.getSelectChain();
        if (this === selectedChain) {
            if (!this.graphics.strokeColor.equals(cc.Color.YELLOW)) {
                cc.log('red..');
                this.graphics.strokeColor = cc.Color.YELLOW;
                this._updateGraphics();
            }
        } else {
            if (!this.graphics.strokeColor.equals(cc.Color.WHITE)) {
                cc.log('yellow..');
                this.graphics.strokeColor = cc.Color.WHITE;
                this._updateGraphics();
            }
        }
    },

    getBkpByItemModel(itemModel) {
        return this._lstBkp.find(bkp => {
            return bkp.getItemModel() === itemModel;
        });
    },

    onUpdateBkp(itemModel) {
        // 1. 获取 item里面的两个值
        let startValue = itemModel.beginIdx;
        let endValue = itemModel.endIdx;

        let minIdx = Math.min(startValue, endValue);
        let maxIdx = Math.max(startValue, endValue);

        let maxLenIdx = this.lstDetailItem.length - 1;
        minIdx = myTools.clamp(minIdx, 0, maxLenIdx);
        maxIdx = myTools.clamp(maxIdx, 0, maxLenIdx);

        let bkp = this.getBkpByItemModel(itemModel);
        bkp.setType(itemModel.bkpType);
        bkp.clean();
        for (let i = minIdx; i <= maxIdx; ++i) {
            let item = this.getDetailItem(i);
            bkp.addItem(item);
        }
        bkp.updateDatas();
    },

    getDetailItem(idx) {
        return this.lstDetailItem[idx];
    },

    onAddBkpItem(itemModel) {
        let beginIdx = itemModel.beginIdx;
        let endIdx = itemModel.endIdx;

        let minIdx = Math.min(beginIdx, endIdx);
        let maxIdx = Math.max(beginIdx, endIdx);

        let nd_bkp = cc.instantiate(G.gameMap.pf_bkp);
        nd_bkp.setParent(this.node);
        let bkp = nd_bkp.getComponent('bkp');
        bkp.setItemModel(itemModel);
        bkp.setType(itemModel.bkpType);
        this._lstBkp.push(bkp);

        for (let i = minIdx; i <= maxIdx; ++i) {
            let item = this.getDetailItem(i);
            bkp.addItem(item);
        }
        bkp.updateDatas();
    },

    onRemoveBkp(itemModel) {
        for (let i = 0, len = this._lstBkp.length; i < len; ++i) {
            let bkp = this._lstBkp[i];
            if (bkp.getItemModel() === itemModel) {
                this._lstBkp.splice(i, 1);
                bkp.node.destroy();
                return;
            }
        }
        console.error(`cannot find bkp!`);
    },

    /**
     * 将 chain 上的所有东西全部都删掉
     */
    clean() {
        this.lstSel.forEach(sel => {
            sel.node.destroy();
        });

        let bkpView = editor.getBkpView();
        this._lstBkp.forEach(bkp => {
            // 对应的UI也应该删除掉
            let itemView = bkpView.getItemViewByItemModel(bkp.getItemModel());
            if (itemView) {
                bkpView.removeItemByView(itemView);
                itemView.destroy();
            }
            bkp.node.destroy();
        });

        this._lstBkp.length = 0;
        this.lstSel.length = 0;
        this.lstDetailItem.length = 0;
        this._updateGraphics();
    },

    _updateHead() {
        if (this.lstSel.length > 0) {
            this.nd_head.active = true;

            let firstSel = this.lstSel[0];
            this.nd_head.setPosition(firstSel.node.x, firstSel.node.y);
        } else {
            this.nd_head.active = false;
        }
    },

    getTotalLen() {
        return this.lstDetailItem.length;
    },

    parseData(chainData) {
        // let mapScene = window.editor.gameApp;
        let ps = chainData.ps;
        // ps.forEach(item => {
        //     // let selnode = this.addSelNode(new Vec2(item.x, item.y));
        //     // this.updateChain();
        //     // mapScene.setCurSelNode(selnode);
        //
        //     this.addSel(cc.v2(item.x,item.y));
        // });
        this.addLstSel(ps);

        // bkp
        let bkpIds = chainData.bkpIds;
        // let chainControl = window.editor.ui.chainControl;
        if (bkpIds) {
            let bkpView = editor.getBkpView();
            bkpIds.forEach(item => {
                let s = item.s;
                let e = item.e;
                let type = item.type;
                // let bkpItem = chainControl.addItem();
                // bkpItem.updateData(s,e,type);
                bkpView.addBkpItem(s, e, type);
            });
        }
    },

    // export
    /**
     *
     * @param ignore 是否忽略不完整的chain.
     *               导出的时候需要忽略,
     *               undo的时候,不能忽略
     * @return {null}
     */
    getModel(ignore = true) {

        if (this.lstSel.length < 3 ||
            this.lstDetailItem.length < 1) {
            if(ignore){
                return null;
            }
        }

        let obj = {};

        obj.ps = []; // 点
        for (let i = 0, len = this.lstSel.length; i < len; ++i) {
            let selnode = this.lstSel[i].node;
            obj.ps.push({
                x: selnode.x,
                y: selnode.y,
            });
        }

        // 分割点
        obj.bkpIds = [];
        for (let i = 0, len = this._lstBkp.length; i < len; ++i) {
            let itemModel = this._lstBkp[i].getItemModel();

            //
            let item = {};
            let a = itemModel.beginIdx;
            let b = itemModel.endIdx;
            item.s = Math.min(a, b);
            item.e = Math.max(a, b);
            item.type = itemModel.bkpType;
            obj.bkpIds.push(item);
        }

        return obj;
    },

});

